package org.Yiran.timetale_re.item;

import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.data.worldgen.features.OreFeatures;
import net.minecraft.data.worldgen.placement.OrePlacements;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.DropExperienceBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.VerticalAnchor;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration;
import net.minecraft.world.level.levelgen.placement.*;
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockMatchTest;
import net.minecraft.world.level.levelgen.structure.templatesystem.RuleTest;
import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.material.MapColor;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import org.Yiran.timetale_re.Timetale_re;
import org.Yiran.timetale_re.worldgen.ModConfiguredFeatures;
import org.Yiran.timetale_re.worldgen.ModPlacedFeatures;
import org.Yiran.timetale_re.worldgen.ModOreFeatures;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;

/**
 * 材料注册管理类
 * <p>
 * 该类负责管理模组中所有材料相关物品和方块的注册。
 * 包括各种金属材料的锭、粒、块、粗矿、粉末等物品，
 * 以及对应的矿石方块和粗矿块方块。
 * 使用Forge的DeferredRegister系统来延迟注册物品和方块，
 * 确保在正确的时机进行注册。
 * </p>
 */
@Mod.EventBusSubscriber(modid = Timetale_re.MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class MaterialRegister {
    
    // ==============================
    // 注册器定义
    // ==============================

    /**
     * 材料物品延迟注册器
     * <p>
     * 使用Forge的DeferredRegister系统创建材料物品注册器，
     * 确保物品在适当的时机被注册到游戏系统中。
     * </p>
     */
    public static final DeferredRegister<Item> MATERIAL_ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, Timetale_re.MODID);
    
    /**
     * 材料方块延迟注册器
     * <p>
     * 使用Forge的DeferredRegister系统创建材料方块注册器，
     * 确保方块在适当的时机被注册到游戏系统中。
     * </p>
     */
    public static final DeferredRegister<Block> MATERIAL_BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, Timetale_re.MODID);

    // ==============================
    // 枚举定义
    // ==============================

    /**
     * 材料类型枚举
     * <p>
     * 定义材料可能需要注册的物品类型。
     * 每种材料可以包含多种类型，如锭、粒、块等。
     * </p>
     */
    public enum MaterialType {
        /** 锭类型 */
        INGOT,   
        /** 粒类型 */
        NUGGET,  
        /** 块类型 */
        BLOCK,   
        /** 粉末类型 */
        DUST,    
        /** 粗矿块类型 */
        RAW_BLOCK 
    }

    /**
     * 矿物类型枚举
     * <p>
     * 定义矿物的类型，包括普通矿石和深板岩矿石。
     * </p>
     */
    public enum OreType {
        /** 普通矿石 */
        ORE,        
        /** 深板岩矿石 */
        DEEPSLATE_ORE 
    }

    // ==============================
    // 材料定义类
    // ==============================

    /**
     * 材料定义类
     * <p>
     * 该类定义了一种材料的所有属性和注册信息，
     * 包括材料名称、类型、属性、矿石信息、烧制配方等。
     * </p>
     */
    public static class MaterialDefinition {
        // ==============================
        // 材料属性字段
        // ==============================

        /** 材料名称 */
        private final String name;
        /** 材料类型列表 */
        private final List<MaterialType> types;
        /** 矿物类型列表 */
        private final List<OreType> oreTypes;
        /** 物品属性配置 */
        private final Item.Properties properties;
        /** 是否有矿石 */
        private final boolean hasOre;
        /** 挖掘等级 */
        private final int harvestLevel;
        /** 经验值最小值 */
        private final int experienceMin;
        /** 经验值最大值 */
        private final int experienceMax;
        /** 是否有烧制配方 */
        private final boolean hasSmeltingRecipe;
        /** 烧制经验 */
        private final float smeltingExperience;
        /** 烧制时间 */
        private final int smeltingTime;
        /** 方块硬度 */
        private final float blockHardness;
        /** 方块爆炸抗性 */
        private final float blockExplosionResistance;
        /** 矿石硬度 */
        private final float oreHardness;
        /** 深板岩矿石硬度 */
        private final float deepslateOreHardness;
        /** 矿石爆炸抗性 */
        private final float oreExplosionResistance;
        
        // 世界生成参数
        /** 普通矿脉最小大小 */
        private final int veinSizeMin;
        /** 普通矿脉最大大小 */
        private final int veinSizeMax;
        /** 深层矿脉最小大小 */
        private final int deepslateVeinSizeMin;
        /** 深层矿脉最大大小 */
        private final int deepslateVeinSizeMax;
        /** 矿脉数量 */
        private final int veinCount;
        /** 最小生成高度 */
        private final int minHeight;
        /** 最大生成高度 */
        private final int maxHeight;

        // ==============================
        // 注册对象字段
        // ==============================

        /** 锭物品注册对象 */
        private RegistryObject<Item> ingot;
        /** 粒物品注册对象 */
        private RegistryObject<Item> nugget;
        /** 粗矿物品注册对象 */
        private RegistryObject<Item> raw;
        /** 粉末物品注册对象 */
        private RegistryObject<Item> dust;
        /** 块方块注册对象 */
        private RegistryObject<Block> block;
        /** 块方块物品注册对象 */
        private RegistryObject<Item> blockItem;
        /** 普通矿石方块注册对象 */
        private RegistryObject<Block> ore;
        /** 普通矿石方块物品注册对象 */
        private RegistryObject<Item> oreItem;
        /** 深板岩矿石方块注册对象 */
        private RegistryObject<Block> deepslateOre;
        /** 深板岩矿石方块物品注册对象 */
        private RegistryObject<Item> deepslateOreItem;
        /** 粗矿块方块注册对象 */
        private RegistryObject<Block> rawBlock;
        /** 粗矿块方块物品注册对象 */
        private RegistryObject<Item> rawBlockItem;
        
        // 世界生成特征注册对象
        private RegistryObject<ConfiguredFeature<OreConfiguration, ?>> configuredFeature;
        private RegistryObject<ConfiguredFeature<OreConfiguration, ?>> deepslateConfiguredFeature;
        private RegistryObject<PlacedFeature> placedFeature;
        private RegistryObject<PlacedFeature> deepslatePlacedFeature;
        
        // ==============================
        // 构造方法
        // ==============================

        /**
         * 材料定义构造函数（无世界生成参数）
         * <p>
         * 创建一个新的材料定义实例，包含所有必要参数，但不包括世界生成参数（用于无矿石材料）。
         * </p>
         *
         * @param name                      材料名称
         * @param types                     材料类型列表
         * @param properties                物品属性配置
         * @param hasOre                    是否有矿石
         * @param oreTypes                  矿物类型列表
         * @param harvestLevel              挖掘等级
         * @param experienceMin             经验值最小值
         * @param experienceMax             经验值最大值
         * @param hasSmeltingRecipe         是否有烧制配方
         * @param smeltingExperience        烧制经验
         * @param smeltingTime              烧制时间
         * @param blockHardness             方块硬度
         * @param blockExplosionResistance  方块爆炸抗性
         * @param oreHardness               矿石硬度
         * @param deepslateOreHardness      深板岩矿石硬度
         * @param oreExplosionResistance    矿石爆炸抗性
         */
        // 主构造函数，包含所有参数（无世界生成参数）
        public MaterialDefinition(String name, List<MaterialType> types, Item.Properties properties,
                            boolean hasOre, List<OreType> oreTypes, int harvestLevel,
                            int experienceMin, int experienceMax, boolean hasSmeltingRecipe,
                            float smeltingExperience, int smeltingTime,
                            float blockHardness, float blockExplosionResistance,
                            float oreHardness, float deepslateOreHardness, float oreExplosionResistance) {
            this(name, types, properties, hasOre, oreTypes, harvestLevel, experienceMin, experienceMax,
                 hasSmeltingRecipe, smeltingExperience, smeltingTime, blockHardness, blockExplosionResistance,
                 oreHardness, deepslateOreHardness, oreExplosionResistance, 0, 0, 0, 0, 0, 0, 0);
        }

        /**
         * 材料定义构造函数（有世界生成参数）
         * <p>
         * 创建一个新的材料定义实例，包含所有必要参数，包括世界生成参数（用于有矿石材料）。
         * </p>
         *
         * @param name                      材料名称
         * @param types                     材料类型列表
         * @param properties                物品属性配置
         * @param hasOre                    是否有矿石
         * @param oreTypes                  矿物类型列表
         * @param harvestLevel              挖掘等级
         * @param experienceMin             经验值最小值
         * @param experienceMax             经验值最大值
         * @param hasSmeltingRecipe         是否有烧制配方
         * @param smeltingExperience        烧制经验
         * @param smeltingTime              烧制时间
         * @param blockHardness             方块硬度
         * @param blockExplosionResistance  方块爆炸抗性
         * @param oreHardness               矿石硬度
         * @param deepslateOreHardness      深板岩矿石硬度
         * @param oreExplosionResistance    矿石爆炸抗性
         * @param veinSizeMin               普通矿脉最小大小
         * @param veinSizeMax               普通矿脉最大大小
         * @param deepslateVeinSizeMin      深层矿脉最小大小
         * @param deepslateVeinSizeMax      深层矿脉最大大小
         * @param veinCount                 矿脉数量
         * @param minHeight                 最小生成高度
         * @param maxHeight                 最大生成高度
         */
        // 主构造函数，包含所有参数（有世界生成参数）
        public MaterialDefinition(String name, List<MaterialType> types, Item.Properties properties,
                                boolean hasOre, List<OreType> oreTypes, int harvestLevel,
                                int experienceMin, int experienceMax, boolean hasSmeltingRecipe,
                                float smeltingExperience, int smeltingTime,
                                float blockHardness, float blockExplosionResistance,
                                float oreHardness, float deepslateOreHardness, float oreExplosionResistance,
                                int veinSizeMin, int veinSizeMax, 
                                int deepslateVeinSizeMin, int deepslateVeinSizeMax,
                                int veinCount, int minHeight, int maxHeight) {
            this.name = name;
            this.types = new ArrayList<>(types);
            this.properties = properties;
            this.hasOre = hasOre;
            this.oreTypes = oreTypes != null ? new ArrayList<>(oreTypes) : new ArrayList<>();
            this.harvestLevel = harvestLevel;
            this.experienceMin = experienceMin;
            this.experienceMax = experienceMax;
            // 只有当有矿石时才真正启用烧制配方
            this.hasSmeltingRecipe = hasOre && hasSmeltingRecipe;
            this.smeltingExperience = smeltingExperience;
            this.smeltingTime = smeltingTime;
            // 设置硬度和爆炸抗性
            this.blockHardness = blockHardness;
            this.blockExplosionResistance = blockExplosionResistance;
            this.oreHardness = oreHardness;
            this.deepslateOreHardness = deepslateOreHardness;
            this.oreExplosionResistance = oreExplosionResistance;
            // 设置世界生成参数
            this.veinSizeMin = veinSizeMin;
            this.veinSizeMax = veinSizeMax;
            this.deepslateVeinSizeMin = deepslateVeinSizeMin;
            this.deepslateVeinSizeMax = deepslateVeinSizeMax;
            this.veinCount = veinCount;
            this.minHeight = minHeight;
            this.maxHeight = maxHeight;
        }

        // ==============================
        // Getter方法
        // ==============================

        /**
         * 获取材料名称
         * @return 材料名称
         */
        public String getName() { return name; }
        
        /**
         * 设置粉末物品注册对象
         * @param dust 粉末物品注册对象
         */
        public void setDust(RegistryObject<Item> dust) { this.dust = dust; }
        
        /**
         * 获取粉末物品注册对象
         * @return 粉末物品注册对象
         */
        public RegistryObject<Item> getDust() { return dust; }
        
        /**
         * 检查是否有粉末类型
         * @return 如果有粉末类型返回true，否则返回false
         */
        public boolean hasDust() {
            return types.contains(MaterialType.DUST);
        }
        
        /**
         * 获取材料类型列表
         * @return 材料类型列表的副本
         */
        public List<MaterialType> getTypes() { return new ArrayList<>(types); }
        
        /**
         * 获取矿物类型列表
         * @return 矿物类型列表的副本
         */
        public List<OreType> getOreTypes() { return new ArrayList<>(oreTypes); }
        
        /**
         * 获取物品属性配置
         * @return 物品属性配置
         */
        public Item.Properties getProperties() { return properties; }
        
        /**
         * 检查是否有矿石
         * @return 如果有矿石返回true，否则返回false
         */
        public boolean hasOre() { return hasOre; }
        
        /**
         * 检查是否需要粗矿物品
         * @return 如果需要粗矿物品返回true，否则返回false
         */
        public boolean needsRawItem() { return this.hasOre(); }
        
        /**
         * 获取挖掘等级
         * @return 挖掘等级
         */
        public int getHarvestLevel() { return harvestLevel; }
        
        /**
         * 获取经验值最小值
         * @return 经验值最小值
         */
        public int getExperienceMin() { return experienceMin; }
        
        /**
         * 获取经验值最大值
         * @return 经验值最大值
         */
        public int getExperienceMax() { return experienceMax; }
        
        /**
         * 检查是否有烧制配方
         * @return 如果有烧制配方返回true，否则返回false
         */
        public boolean hasSmeltingRecipe() { return hasSmeltingRecipe; }
        
        /**
         * 获取烧制经验
         * @return 烧制经验
         */
        public float getSmeltingExperience() { return smeltingExperience; }
        
        /**
         * 获取烧制时间
         * @return 烧制时间
         */
        public int getSmeltingTime() { return smeltingTime; }
        
        /**
         * 获取方块硬度
         * @return 方块硬度
         */
        public float getBlockHardness() { return blockHardness; }
        
        /**
         * 获取方块爆炸抗性
         * @return 方块爆炸抗性
         */
        public float getBlockExplosionResistance() { return blockExplosionResistance; }
        
        /**
         * 获取矿石硬度
         * @return 矿石硬度
         */
        public float getOreHardness() { return oreHardness; }
        
        /**
         * 获取深板岩矿石硬度
         * @return 深板岩矿石硬度
         */
        public float getDeepslateOreHardness() { return deepslateOreHardness; }
        
        /**
         * 获取矿石爆炸抗性
         * @return 矿石爆炸抗性
         */
        public float getOreExplosionResistance() { return oreExplosionResistance; }
        
        /**
         * 获取普通矿脉最小大小
         * @return 普通矿脉最小大小
         */
        public int getVeinSizeMin() { return veinSizeMin; }
        
        /**
         * 获取普通矿脉最大大小
         * @return 普通矿脉最大大小
         */
        public int getVeinSizeMax() { return veinSizeMax; }
        
        /**
         * 获取普通矿脉大小（平均值）
         * @return 普通矿脉大小平均值
         */
        public int getVeinSize() { return (veinSizeMin + veinSizeMax) / 2; }
        
        /**
         * 获取深层矿脉最小大小
         * @return 深层矿脉最小大小
         */
        public int getDeepslateVeinSizeMin() { return deepslateVeinSizeMin; }
        
        /**
         * 获取深层矿脉最大大小
         * @return 深层矿脉最大大小
         */
        public int getDeepslateVeinSizeMax() { return deepslateVeinSizeMax; }
        
        /**
         * 获取深层矿脉大小（平均值）
         * @return 深层矿脉大小平均值
         */
        public int getDeepslateVeinSize() { return (deepslateVeinSizeMin + deepslateVeinSizeMax) / 2; }
        
        /**
         * 获取矿脉数量
         * @return 矿脉数量
         */
        public int getVeinCount() { return veinCount; }
        
        /**
         * 获取最小生成高度
         * @return 最小生成高度
         */
        public int getMinHeight() { return minHeight; }
        
        /**
         * 获取最大生成高度
         * @return 最大生成高度
         */
        public int getMaxHeight() { return maxHeight; }
        
        /**
         * 设置锭物品注册对象
         * @param ingot 锭物品注册对象
         */
        public void setIngot(RegistryObject<Item> ingot) { this.ingot = ingot; }
        
        /**
         * 设置粒物品注册对象
         * @param nugget 粒物品注册对象
         */
        public void setNugget(RegistryObject<Item> nugget) { this.nugget = nugget; }
        
        /**
         * 设置粗矿物品注册对象
         * @param raw 粗矿物品注册对象
         */
        public void setRaw(RegistryObject<Item> raw) { this.raw = raw; }
        
        /**
         * 设置块方块注册对象
         * @param block 块方块注册对象
         */
        public void setBlock(RegistryObject<Block> block) { this.block = block; }
        
        /**
         * 设置块方块物品注册对象
         * @param blockItem 块方块物品注册对象
         */
        public void setBlockItem(RegistryObject<Item> blockItem) { this.blockItem = blockItem; }
        
        /**
         * 设置普通矿石方块注册对象
         * @param ore 普通矿石方块注册对象
         */
        public void setOre(RegistryObject<Block> ore) { this.ore = ore; }
        
        /**
         * 设置普通矿石方块物品注册对象
         * @param oreItem 普通矿石方块物品注册对象
         */
        public void setOreItem(RegistryObject<Item> oreItem) { this.oreItem = oreItem; }
        
        /**
         * 设置深板岩矿石方块注册对象
         * @param deepslateOre 深板岩矿石方块注册对象
         */
        public void setDeepslateOre(RegistryObject<Block> deepslateOre) { this.deepslateOre = deepslateOre; }
        
        /**
         * 设置深板岩矿石方块物品注册对象
         * @param deepslateOreItem 深板岩矿石方块物品注册对象
         */
        public void setDeepslateOreItem(RegistryObject<Item> deepslateOreItem) { this.deepslateOreItem = deepslateOreItem; }
        
        /**
         * 获取锭物品注册对象
         * @return 锭物品注册对象
         */
        public RegistryObject<Item> getIngot() { return ingot; }
        
        /**
         * 获取粒物品注册对象
         * @return 粒物品注册对象
         */
        public RegistryObject<Item> getNugget() { return nugget; }
        
        /**
         * 获取粗矿物品注册对象
         * @return 粗矿物品注册对象
         */
        public RegistryObject<Item> getRaw() { return raw; }
        
        /**
         * 获取块方块注册对象
         * @return 块方块注册对象
         */
        public RegistryObject<Block> getBlock() { return block; }
        
        /**
         * 获取块方块物品注册对象
         * @return 块方块物品注册对象
         */
        public RegistryObject<Item> getBlockItem() { return blockItem; }
        
        /**
         * 获取普通矿石方块注册对象
         * @return 普通矿石方块注册对象
         */
        public RegistryObject<Block> getOre() { return ore; }
        
        /**
         * 获取普通矿石方块物品注册对象
         * @return 普通矿石方块物品注册对象
         */
        public RegistryObject<Item> getOreItem() { return oreItem; }
        
        /**
         * 获取深板岩矿石方块注册对象
         * @return 深板岩矿石方块注册对象
         */
        public RegistryObject<Block> getDeepslateOre() { return deepslateOre; }
        
        /**
         * 获取深板岩矿石方块物品注册对象
         * @return 深板岩矿石方块物品注册对象
         */
        public RegistryObject<Item> getDeepslateOreItem() { return deepslateOreItem; }
        
        /**
         * 设置粗矿块方块注册对象
         * @param rawBlock 粗矿块方块注册对象
         */
        public void setRawBlock(RegistryObject<Block> rawBlock) { this.rawBlock = rawBlock; }
        
        /**
         * 设置粗矿块方块物品注册对象
         * @param rawBlockItem 粗矿块方块物品注册对象
         */
        public void setRawBlockItem(RegistryObject<Item> rawBlockItem) { this.rawBlockItem = rawBlockItem; }
        
        /**
         * 获取粗矿块方块注册对象
         * @return 粗矿块方块注册对象
         */
        public RegistryObject<Block> getRawBlock() { return rawBlock; }
        
        /**
         * 获取粗矿块方块物品注册对象
         * @return 粗矿块方块物品注册对象
         */
        public RegistryObject<Item> getRawBlockItem() { return rawBlockItem; }
        
        /**
         * 设置配置特征注册对象
         * @param configuredFeature 配置特征注册对象
         */
        public void setConfiguredFeature(RegistryObject<ConfiguredFeature<OreConfiguration, ?>> configuredFeature) {
            this.configuredFeature = configuredFeature;
        }
        
        /**
         * 获取配置特征注册对象
         * @return 配置特征注册对象
         */
        public RegistryObject<ConfiguredFeature<OreConfiguration, ?>> getConfiguredFeature() {
            return configuredFeature;
        }
        
        /**
         * 设置深层配置特征注册对象
         * @param deepslateConfiguredFeature 深层配置特征注册对象
         */
        public void setDeepslateConfiguredFeature(RegistryObject<ConfiguredFeature<OreConfiguration, ?>> deepslateConfiguredFeature) {
            this.deepslateConfiguredFeature = deepslateConfiguredFeature;
        }
        
        /**
         * 获取深层配置特征注册对象
         * @return 深层配置特征注册对象
         */
        public RegistryObject<ConfiguredFeature<OreConfiguration, ?>> getDeepslateConfiguredFeature() {
            return deepslateConfiguredFeature;
        }
        
        /**
         * 设置放置特征注册对象
         * @param placedFeature 放置特征注册对象
         */
        public void setPlacedFeature(RegistryObject<PlacedFeature> placedFeature) {
            this.placedFeature = placedFeature;
        }
        
        /**
         * 获取放置特征注册对象
         * @return 放置特征注册对象
         */
        public RegistryObject<PlacedFeature> getPlacedFeature() {
            return placedFeature;
        }
        
        /**
         * 设置深层放置特征注册对象
         * @param deepslatePlacedFeature 深层放置特征注册对象
         */
        public void setDeepslatePlacedFeature(RegistryObject<PlacedFeature> deepslatePlacedFeature) {
            this.deepslatePlacedFeature = deepslatePlacedFeature;
        }
        
        /**
         * 获取深层放置特征注册对象
         * @return 深层放置特征注册对象
         */
        public RegistryObject<PlacedFeature> getDeepslatePlacedFeature() {
            return deepslatePlacedFeature;
        }
        
        // ==============================
        // 辅助方法
        // ==============================

        /**
         * 检查是否包含特定类型的物品
         * @param type 材料类型
         * @return 如果包含该类型返回true，否则返回false
         */
        // 添加辅助方法来检查特定类型的物品是否存在
        public boolean hasType(MaterialType type) {
            return types.contains(type);
        }
        
        /**
         * 检查是否有粗矿块
         * @return 如果有粗矿块返回true，否则返回false
         */
        public boolean hasRawBlock() {
            return types.contains(MaterialType.RAW_BLOCK);
        }
    }

    // ==============================
    // 材料注册管理
    // ==============================

    /** 存储所有注册的材料列表 */
    private static final List<MaterialDefinition> registeredMaterials = new ArrayList<>();

    /**
     * 注册材料（无世界生成参数）
     * <p>
     * 创建并注册一个新的材料定义（无世界生成参数）。
     * </p>
     *
     * @param name                      材料名称
     * @param types                     材料类型列表
     * @param properties                物品属性配置
     * @param hasOre                    是否有矿石
     * @param oreTypes                  矿物类型列表
     * @param harvestLevel              挖掘等级
     * @param experienceMin             经验值最小值
     * @param experienceMax             经验值最大值
     * @param hasSmeltingRecipe         是否有烧制配方
     * @param smeltingExperience        烧制经验
     * @param smeltingTime              烧制时间
     * @param blockHardness             方块硬度
     * @param blockExplosionResistance  方块爆炸抗性
     * @param oreHardness               矿石硬度
     * @param deepslateOreHardness      深板岩矿石硬度
     * @param oreExplosionResistance    矿石爆炸抗性
     * @return 材料定义对象
     */
    public static MaterialDefinition registerMaterial(

            String name,
            List<MaterialType> types,
            Item.Properties properties,
            boolean hasOre,
            List<OreType> oreTypes,
            int harvestLevel,
            int experienceMin,
            int experienceMax,
            boolean hasSmeltingRecipe,
            float smeltingExperience,
            int smeltingTime,
            float blockHardness,
            float blockExplosionResistance,
            float oreHardness,
            float deepslateOreHardness,
            float oreExplosionResistance

    )

    {
        MaterialDefinition material =

                new MaterialDefinition(
                        name,
                        types,
                        properties,
                        hasOre,
                        oreTypes,
                        harvestLevel,
                        experienceMin,
                        experienceMax,
                        hasSmeltingRecipe,
                        smeltingExperience,
                        smeltingTime,
                        blockHardness,
                        blockExplosionResistance,
                        oreHardness,
                        deepslateOreHardness,
                        oreExplosionResistance

                );

        return registerAndInitializeMaterial(material);

    }
    
    /**
     * 注册材料（有世界生成参数）
     * <p>
     * 创建并注册一个新的材料定义（有世界生成参数）。
     * </p>
     *
     * @param name                      材料名称
     * @param types                     材料类型列表
     * @param properties                物品属性配置
     * @param hasOre                    是否有矿石
     * @param oreTypes                  矿物类型列表
     * @param harvestLevel              挖掘等级
     * @param experienceMin             经验值最小值
     * @param experienceMax             经验值最大值
     * @param hasSmeltingRecipe         是否有烧制配方
     * @param smeltingExperience        烧制经验
     * @param smeltingTime              烧制时间
     * @param blockHardness             方块硬度
     * @param blockExplosionResistance  方块爆炸抗性
     * @param oreHardness               矿石硬度
     * @param deepslateOreHardness      深板岩矿石硬度
     * @param oreExplosionResistance    矿石爆炸抗性
     * @param veinSizeMin               普通矿脉最小大小
     * @param veinSizeMax               普通矿脉最大大小
     * @param deepslateVeinSizeMin      深层矿脉最小大小
     * @param deepslateVeinSizeMax      深层矿脉最大大小
     * @param veinCount                 矿脉数量
     * @param minHeight                 最小生成高度
     * @param maxHeight                 最大生成高度
     * @return 材料定义对象
     */
    public static MaterialDefinition registerMaterial(

            String name,
            List<MaterialType> types,
            Item.Properties properties,
            boolean hasOre,
            List<OreType> oreTypes,
            int harvestLevel,
            int experienceMin,
            int experienceMax,
            boolean hasSmeltingRecipe,
            float smeltingExperience,
            int smeltingTime,
            float blockHardness,
            float blockExplosionResistance,
            float oreHardness,
            float deepslateOreHardness,
            float oreExplosionResistance,
            int veinSizeMin,
            int veinSizeMax,
            int deepslateVeinSizeMin,
            int deepslateVeinSizeMax,
            int veinCount,
            int minHeight,
            int maxHeight

    )

    {
        MaterialDefinition material =

                new MaterialDefinition(
                        name,
                        types,
                        properties,
                        hasOre,
                        oreTypes,
                        harvestLevel,
                        experienceMin,
                        experienceMax,
                        hasSmeltingRecipe,
                        smeltingExperience,
                        smeltingTime,
                        blockHardness,
                        blockExplosionResistance,
                        oreHardness,
                        deepslateOreHardness,
                        oreExplosionResistance,
                        veinSizeMin,
                        veinSizeMax,
                        deepslateVeinSizeMin,
                        deepslateVeinSizeMax,
                        veinCount,
                        minHeight,
                        maxHeight

                );

        return registerAndInitializeMaterial(material);

    }

    /**
     * 注册并初始化材料
     * <p>
     * 将材料添加到注册列表并初始化其物品注册。
     * </p>
     *
     * @param material 材料定义对象
     * @return 材料定义对象
     */
    // 提取公共注册逻辑
    private static MaterialDefinition registerAndInitializeMaterial(MaterialDefinition material) {
        registeredMaterials.add(material);
        registerMaterialItems(material);
        return material;
    }

    // ==============================
    // 物品注册方法
    // ==============================

    /**
     * 根据材料定义注册相关物品
     * <p>
     * 根据材料定义中的类型信息注册相应的物品和方块。
     * </p>
     *
     * @param material 材料定义对象
     */
    private static void registerMaterialItems(MaterialDefinition material) {
        // 按类型顺序注册基础物品类型
        // 先注册锭
        if (material.hasType(MaterialType.INGOT)) {
            registerItemType(material, MaterialType.INGOT);
        }

        // 再注册粒
        if (material.hasType(MaterialType.NUGGET)) {
            registerItemType(material, MaterialType.NUGGET);
        }

        // 再注册块
        if (material.hasType(MaterialType.BLOCK)) {
            registerItemType(material, MaterialType.BLOCK);
        }

        // 再注册粗矿块
        if (material.hasType(MaterialType.RAW_BLOCK) && material.hasOre()) {
            registerItemType(material, MaterialType.RAW_BLOCK);
        }

        // 最后注册粉
        if (material.hasType(MaterialType.DUST)) {
            registerItemType(material, MaterialType.DUST);
        }

        // 注册粗矿物品（如果需要）
        if (material.hasOre()) {
            RegistryObject<Item> raw = MATERIAL_ITEMS.register("raw_" + material.getName(),
                    () -> new Item(material.getProperties()));
            material.setRaw(raw);

            // 注册矿物方块
            registerOreBlocks(material);
        }
    }

    /**
     * 注册特定类型的物品
     * <p>
     * 根据材料类型注册相应的物品或方块。
     * </p>
     *
     * @param material 材料定义对象
     * @param type     材料类型
     */
    // 提取物品类型注册逻辑
    private static void registerItemType(MaterialDefinition material, MaterialType type) {
        switch (type) {
            case INGOT:
                RegistryObject<Item> ingot = MATERIAL_ITEMS.register(material.getName() + "_ingot",
                        () -> new Item(material.getProperties()));
                material.setIngot(ingot);
                break;
            case NUGGET:
                RegistryObject<Item> nugget = MATERIAL_ITEMS.register(material.getName() + "_nugget",
                        () -> new Item(material.getProperties()));
                material.setNugget(nugget);
                break;
            case BLOCK:
                RegistryObject<Block> block = MATERIAL_BLOCKS.register(material.getName() + "_block",
                        () -> new Block(BlockBehaviour.Properties.copy(Blocks.IRON_BLOCK)
                                .strength(material.getBlockHardness(), material.getBlockExplosionResistance())
                                .requiresCorrectToolForDrops()) {
                            @Override
                            @SuppressWarnings("deprecation")
                            public @NotNull List<ItemStack> getDrops(@NotNull BlockState state, @NotNull LootParams.Builder builder) {
                                // 确保方块掉落自身
                                return Collections.singletonList(new ItemStack(this));
                            }
                        });
                material.setBlock(block);
                // 注册方块物品
                RegistryObject<Item> blockItem = MATERIAL_ITEMS.register(material.getName() + "_block",
                        () -> new BlockItem(block.get(), material.getProperties()));
                material.setBlockItem(blockItem);
                break;
            case DUST:
                RegistryObject<Item> dust = MATERIAL_ITEMS.register(material.getName() + "_dust",
                        () -> new Item(material.getProperties()));
                material.setDust(dust);
                break;
            case RAW_BLOCK:
                RegistryObject<Block> rawBlock = MATERIAL_BLOCKS.register("raw_" + material.getName() + "_block",
                        () -> new Block(BlockBehaviour.Properties.copy(Blocks.RAW_IRON_BLOCK)
                                .strength(material.getOreHardness(), material.getOreExplosionResistance())
                                .requiresCorrectToolForDrops()) {
                            @Override
                            @SuppressWarnings("deprecation")
                            public @NotNull List<ItemStack> getDrops(@NotNull BlockState state, @NotNull LootParams.Builder builder) {
                                // 确保方块掉落自身
                                return Collections.singletonList(new ItemStack(this));
                            }
                        });
                material.setRawBlock(rawBlock);
                // 注册粗矿块物品
                RegistryObject<Item> rawBlockItem = MATERIAL_ITEMS.register("raw_" + material.getName() + "_block",
                        () -> new BlockItem(rawBlock.get(), material.getProperties()));
                material.setRawBlockItem(rawBlockItem);
                break;
        }
    }

    // ==============================
    // 矿物方块注册方法
    // ==============================

    /**
     * 根据材料定义注册矿物方块
     * <p>
     * 根据材料定义中的矿物类型信息注册相应的矿物方块。
     * </p>
     *
     * @param material 材料定义对象
     */
    private static void registerOreBlocks(MaterialDefinition material) {
        for (OreType oreType : material.getOreTypes()) {
            registerOreType(material, oreType);
        }
    }

    /**
     * 注册特定类型的矿物
     * <p>
     * 根据矿物类型注册相应的矿物方块。
     * </p>
     *
     * @param material 材料定义对象
     * @param oreType  矿物类型
     */
    // 提取矿物类型注册逻辑
    private static void registerOreType(MaterialDefinition material, OreType oreType) {
        switch (oreType) {
            case ORE:
                RegistryObject<Block> oreBlock = MATERIAL_BLOCKS.register(material.getName() + "_ore",
                        () -> createOreBlock(material, MapColor.STONE, material.getOreHardness(), material.getOreExplosionResistance()));
                material.setOre(oreBlock);

                RegistryObject<Item> oreItem = MATERIAL_ITEMS.register(material.getName() + "_ore",
                        () -> new BlockItem(oreBlock.get(), material.getProperties()));
                material.setOreItem(oreItem);
                break;

            case DEEPSLATE_ORE:
                RegistryObject<Block> deepslateOreBlock = MATERIAL_BLOCKS.register("deepslate_" + material.getName() + "_ore",
                        () -> createOreBlock(material, MapColor.DEEPSLATE, material.getDeepslateOreHardness(), material.getOreExplosionResistance()));
                material.setDeepslateOre(deepslateOreBlock);

                RegistryObject<Item> deepslateOreItem = MATERIAL_ITEMS.register("deepslate_" + material.getName() + "_ore",
                        () -> new BlockItem(deepslateOreBlock.get(), material.getProperties()));
                material.setDeepslateOreItem(deepslateOreItem);
                break;
        }
    }

    // ==============================
    // 辅助方法
    // ==============================

    /**
     * 创建矿石方块的辅助方法
     * <p>
     * 创建具有指定属性的矿石方块，包括地图颜色、硬度、爆炸抗性等。
     * </p>
     *
     * @param material            材料定义对象
     * @param mapColor            地图颜色
     * @param strength            硬度
     * @param explosionResistance 爆炸抗性
     * @return 矿石方块实例
     */
    private static DropExperienceBlock createOreBlock(MaterialDefinition material, MapColor mapColor,
                                                      float strength, float explosionResistance) {
        // 根据地图颜色选择基础方块类型
        Block baseBlock = (mapColor == MapColor.DEEPSLATE) ? Blocks.DEEPSLATE_IRON_ORE : Blocks.IRON_ORE;

        // 构建方块属性
        BlockBehaviour.Properties properties = BlockBehaviour.Properties.copy(baseBlock)
                .mapColor(mapColor)
                .strength(strength, explosionResistance)
                .requiresCorrectToolForDrops();

        return new DropExperienceBlock(properties,
                UniformInt.of(material.getExperienceMin(), material.getExperienceMax())) {
            @Override
            @SuppressWarnings("deprecation")
            public @NotNull List<ItemStack> getDrops(@NotNull BlockState state, @NotNull LootParams.Builder builder) {
                // 获取使用的工具
                ItemStack tool = builder.getParameter(LootContextParams.TOOL);

                // 获取时运附魔等级
                int fortuneLevel = tool.getEnchantmentLevel(Enchantments.BLOCK_FORTUNE);

                // 计算掉落数量（基础数量1 + 时运附魔增加的数量）
                int count = 1;
                if (fortuneLevel > 0) {
                    // 根据时运等级随机增加掉落数量
                    count += builder.getLevel().getRandom().nextInt(fortuneLevel + 1);
                }

                // 获取默认的掉落物（经验）
                List<ItemStack> drops = super.getDrops(state, builder);

                // 添加自定义掉落物（对应材料的粗矿）
                if (material.getRaw() != null) {
                    drops.add(new ItemStack(material.getRaw().get(), count));
                }

                return drops;
            }
        };
    }

    // ==============================
    // 世界生成相关方法
    // ==============================

    /**
     * 注册所有材料的世界生成特征
     * <p>
     * 为所有有矿石的材料注册配置特征和放置特征
     * </p>
     */
    public static void registerWorldGenFeatures() {
        for (MaterialDefinition material : registeredMaterials) {
            if (material.hasOre()) {
                registerMaterialWorldGenFeatures(material);
            }
        }
    }
    
    /**
     * 注册单个材料的世界生成特征
     * <p>
     * 为指定材料注册配置特征和放置特征
     * </p>
     *
     * @param material 材料定义对象
     */
    private static void registerMaterialWorldGenFeatures(MaterialDefinition material) {
        // 注册配置特征
        registerMaterialConfiguredFeature(material);
        
        // 注册放置特征
        registerMaterialPlacedFeature(material);
    }
    
    /**
     * 注册单个材料的配置特征
     * <p>
     * 为指定材料注册配置特征
     * </p>
     *
     * @param material 材料定义对象
     */
    private static void registerMaterialConfiguredFeature(MaterialDefinition material) {
        // 注册普通矿石配置特征
        if (material.getOre() != null) {
            List<OreConfiguration.TargetBlockState> stoneOres = List.of(
                OreConfiguration.target(
                    new TagMatchTest(BlockTags.STONE_ORE_REPLACEABLES), 
                    material.getOre().get().defaultBlockState())
            );
            
            RegistryObject<ConfiguredFeature<OreConfiguration, ?>> configuredFeature = 
                ModOreFeatures.CONFIGURED_FEATURES.register(material.getName() + "_ore", 
                    () -> new ConfiguredFeature<>(Feature.ORE, 
                        new OreConfiguration(stoneOres, material.getVeinSizeMax())));
            material.setConfiguredFeature(configuredFeature);
        }
        
        // 注册深层矿石配置特征
        if (material.getDeepslateOre() != null) {
            List<OreConfiguration.TargetBlockState> deepslateOres = List.of(
                OreConfiguration.target(
                    new TagMatchTest(BlockTags.DEEPSLATE_ORE_REPLACEABLES), 
                    material.getDeepslateOre().get().defaultBlockState())
            );
            
            RegistryObject<ConfiguredFeature<OreConfiguration, ?>> deepslateConfiguredFeature = 
                ModOreFeatures.CONFIGURED_FEATURES.register("deepslate_" + material.getName() + "_ore", 
                    () -> new ConfiguredFeature<>(Feature.ORE, 
                        new OreConfiguration(deepslateOres, material.getDeepslateVeinSizeMax())));
            material.setDeepslateConfiguredFeature(deepslateConfiguredFeature);
        }
    }
    
    /**
     * 注册单个材料的放置特征
     * <p>
     * 为指定材料注册放置特征
     * </p>
     *
     * @param material 材料定义对象
     */
    private static void registerMaterialPlacedFeature(MaterialDefinition material) {
        // 注册普通矿石放置特征
        if (material.getConfiguredFeature() != null) {
            RegistryObject<PlacedFeature> placedFeature = 
                ModOreFeatures.PLACED_FEATURES.register(material.getName() + "_ore",
                    () -> new PlacedFeature((Holder<ConfiguredFeature<?, ?>>) (Holder<?>) material.getConfiguredFeature().getHolder().get(), List.of(
                            CountPlacement.of(material.getVeinCount()),
                            InSquarePlacement.spread(),
                            HeightRangePlacement.uniform(VerticalAnchor.absolute(material.getMinHeight()), 
                                    VerticalAnchor.absolute(material.getMaxHeight())),
                            BiomeFilter.biome()
                    )));
            material.setPlacedFeature(placedFeature);
        }
        
        // 注册深层矿石放置特征
        if (material.getDeepslateConfiguredFeature() != null) {
            RegistryObject<PlacedFeature> deepslatePlacedFeature = 
                ModOreFeatures.PLACED_FEATURES.register("deepslate_" + material.getName() + "_ore",
                    () -> new PlacedFeature((Holder<ConfiguredFeature<?, ?>>) (Holder<?>) material.getDeepslateConfiguredFeature().getHolder().get(), List.of(
                            CountPlacement.of(material.getVeinCount()),
                            InSquarePlacement.spread(),
                            HeightRangePlacement.uniform(VerticalAnchor.absolute(material.getMinHeight()), 
                                    VerticalAnchor.absolute(material.getMaxHeight())),
                            BiomeFilter.biome()
                    )));
            material.setDeepslatePlacedFeature(deepslatePlacedFeature);
        }
    }

    // ==============================
    // 公共访问方法
    // ==============================

    /**
     * 获取所有注册的材料
     * <p>
     * 返回包含所有已注册材料定义的列表。
     * </p>
     *
     * @return 所有已注册材料的列表
     */
    public static List<MaterialDefinition> getRegisteredMaterials() {
        return new ArrayList<>(registeredMaterials);
    }

}